package systemc;

import framework.AscTimeSorterAndMerger;
import framework.Constants;
import framework.Dropper;
import framework.FileDataSource;
import framework.WildPointExtrapolator;
import framework.detectors.ExceedDetector;
import framework.detectors.OutOfRangeDetector;
import framework.sinkers.FileSink;
import framework.sinkers.SystemsABCFormatter;

import java.io.FileNotFoundException;

/**
 */
public class SystemCPlumber {

    public static final int MIN_PRESSURE                    = 45;
    public static final int MAX_PRESSURE                    = 90;

    public static final int MAX_ATTITUDE                    = 10;
    public static final int MAX_PRESSURE_WITH_MAX_ATT       = 65;


    public static void main(String [] args) throws FileNotFoundException, InterruptedException {
    	
    	// verify if there are sufficient arguments to start the program
    	if(args.length != 5){
    		System.out.println("Wrong usage of program arguments!");
    		System.out.println("Systems usage: <Source filename1> <Source filename2> <Sink filename> <Sink filename WP_Pressure> <Sink filename WP_AttitudePressure>\n \t ");
    		System.exit(0);
    	}
    	
    	String argSource1                      = args[0];
        String argSource2                      = args[1];
        String argSink                         = args[2];
        String argSinkWPPress                  = args[3];
        String argSinkWPAttPress               = args[4];

        // Datasource filters ----------------------------
        FileDataSource src1 = new FileDataSource(argSource1);
        FileDataSource src2 = new FileDataSource(argSource2);

        // SortedMerger filter ---------------------------------------------
        AscTimeSorterAndMerger sortedMerger = new AscTimeSorterAndMerger(2);

        //create the WP extrapolator for pressure out-of-range----------------------------------------------------------
        int [] idsToExtrapolatePress = {Constants.PRESSURE_ID};
        OutOfRangeDetector pressOutRangeDetector = new OutOfRangeDetector(MIN_PRESSURE, MAX_PRESSURE);
        WildPointExtrapolator wpExtrapolPress = new WildPointExtrapolator(idsToExtrapolatePress, pressOutRangeDetector);

        //create the pressure wp data sink
        int [] printOrderPressureWP = {Constants.TIME_ID, Constants.PRESSURE_ID};
        FileSink wpPressSink = new FileSink(argSinkWPPress, printOrderPressureWP, new SystemsABCFormatter());


        //create the WP extrapolator for excessive pressure and attitude together --------------------------------------
        int [] idsToExtrapolateAttPress = {Constants.ATTITUDE_ID, Constants.PRESSURE_ID};
        ExceedDetector exceedDetector = new ExceedDetector( new double[]{MAX_ATTITUDE, MAX_PRESSURE_WITH_MAX_ATT});
        WildPointExtrapolator wpExtrapolAttPress = new WildPointExtrapolator( idsToExtrapolateAttPress, exceedDetector);

        //create the attitude + pressure wp data sink
        int [] printOrderAttPressureWP = {Constants.TIME_ID, Constants.ATTITUDE_ID, Constants.PRESSURE_ID};
        FileSink wpAttPressSink = new FileSink(argSinkWPAttPress, printOrderAttPressureWP, new SystemsABCFormatter());


        // Dropper ------------------------
        int [] toDrop = {Constants.VELOCITY_ID};
        Dropper drop = new Dropper(toDrop);

        
        //create the main data sink
        int [] printOrderMain = {Constants.TIME_ID, Constants.TEMPERATURE_ID, Constants.ALTITUDE_ID, Constants.PRESSURE_ID};
        FileSink mainSink = new FileSink(argSink, printOrderMain, new SystemsABCFormatter());


        //connect everything
        mainSink.Connect(wpExtrapolAttPress,0);
        wpAttPressSink.Connect(wpExtrapolAttPress,1);

        wpExtrapolAttPress.Connect(wpExtrapolPress,0,0);
        wpPressSink.Connect(wpExtrapolPress,1);

        wpExtrapolPress.Connect(drop,0,0);

        drop.Connect(sortedMerger,0);

        sortedMerger.Connect(src1,0,0);

        sortedMerger.Connect(src2,1,0);

        //start filters
        src1.start();
        src2.start();
        sortedMerger.start();
        drop.start();
        wpExtrapolPress.start();
        wpPressSink.start();
        wpExtrapolAttPress.start();
        wpAttPressSink.start();
        mainSink.start();

    }

}
